package com.mt.fpb.utils;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mt.fpb.mapper.*;

import com.mt.fpb.model.EarningDetail;
import com.mt.fpb.model.TransactionRecords;
import com.mt.fpb.model.WxProduct;
import com.mt.fpb.model.WxProductOrder;
import com.vbao.service.trade.VbaoChargeSystemHandler;
import com.vbao.service.trade.bean.request.QRCodeRefundRequest;
import com.vbao.service.trade.bean.request.TradeRequestXml;
import com.vbao.service.trade.utils.Base64;
import com.vbao.service.trade.utils.TradeCodeEnum;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * FileName: OderMoney
 * Author:   wang
 * Date:     2021/8/3 17:00
 */
@Component
@Configuration
@EnableScheduling
@CommonsLog
@Transactional(rollbackFor={Exception.class})//开启事务
public class OrderMoney {

    @Resource
    private OrderMoneyMapper orderMoneyMapper;
    @Resource
    private EarningDetailMapper earningDetailMapper;
    @Resource
    private RedeemMapper redeemMapper;

    @Autowired
    private WxProductOrderMapper wxProductOrderMapper;

    @Autowired
    private WxProductMapper wxProductMapper;

    @Autowired
    private BalanceMapper balanceMapper;

    @Autowired
    private RxEmployeeMapper rxEmployeeMapper;

    @Autowired
    private TransactionRecordsMapper transactionRecordsMapper;
    /**
     * 每天24：00:05定时执行任务，判断已支付且生效的保险产品是否到期
     * 计算每个合规客户产品的单日收益并且更新数据库
     */
    //@Scheduled(cron = "5 0 0 * * ?")
    @Scheduled(cron = "*/5 * * * * ?") //暂时用5秒测试
    private void UpdateOderMoney() {

        try {
            //查询订单表中状态为2(进行中)的订单
            List<WxProductOrder> idList = orderMoneyMapper.selectId(Constants.ONGO);
            Date date = new Date();

            //对客户购买的所有产品进行筛选
            for (WxProductOrder wxProductOrder : idList) {

                Date effectiveTime = wxProductOrder.getEffectiveTime();

                //对筛选的产品进行生效判断
                if (date.after(effectiveTime)) {
                    String id = wxProductOrder.getId();
                    String pid = wxProductOrder.getProductId();
                    Date endTime = wxProductOrder.getEndTime();
                    Float profit = orderMoneyMapper.selectProfit(pid);
                    Float payMoney = wxProductOrder.getPayMoney();
                    Float orderMoney = wxProductOrder.getOrderMoney();
                    Float day = (float) 1 / 365;
                    DecimalFormat decimalFormat = new DecimalFormat();
                    decimalFormat.format(day);

                    //判断客户购买的产品是否到期
                    if (date.after(endTime)) {
                        //说明已经自动到期，开始走自动将钱打到余额中
                        //1 更改状态
                        orderMoneyMapper.updateOrderStatus(wxProductOrder.getId(), Constants.DUE_TO_NORMAL);
                        log.info("订单id为" + id + "已达到正常到期时间，状态已经更改");
                        //2 将这条数据插入或者更新到余额表中
                        saveOrUpdateBalance(wxProductOrder);
                        //3 将这条数据插入到交易记录表
                        saveTransactionRecords(wxProductOrder);

/*                    //System.out.println("开始执行自动赎回");
                    //调用赎回接口付钱给客户
                    redeemMapper.doRedeem(li.getId(),date);
                    //调用退款的方法
                    String id = li.getId();

                    //通过当前订单的产品id查询表中的产品名称
                    QueryWrapper<WxProduct> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("product_id",pid);
                    WxProduct wxProduct = wxProductMapper.selectOne(queryWrapper);
                    String productName = wxProduct.getProductName();
                    //自动赎回的话退款金额就是当前订单产生的利益(即本金+收益金额)就是orderMoney
                    String result = refund(id,orderMoney,productName);*/
                    } else {
                        //每日更新账户价值
                        Float newMoney = (profit * payMoney * day) + orderMoney;
                        orderMoneyMapper.updateOrderMoney(newMoney, wxProductOrder.getId());
                        //每日产生收益明细
//                    EarningDetail earningDetail=new EarningDetail();
//                    String t= String.valueOf(Calendar.getInstance().getTimeInMillis());
//                    String id = UUID.randomUUID().toString().substring(0,5);
//                    earningDetail.setEarningId(pid+t+id);
//                    earningDetail.setProductOrderId(li.getId());
//                    earningDetail.setEmployeeId( orderMoneyMapper.selectUserID(li.getId()));
//                    earningDetail.setOrderMoney(newMoney);
//                    earningDetail.setDayEarnings(profit * payMoney * day);
//                    earningDetail.setDayTime(date);
//                    earningDetailMapper.addEarningDetail(earningDetail);
                    }
                }
            }
        }catch (Exception e) {
            //事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("定时任务UpdateOderMoney出错，请及时查看日志信息", e);
        }

    }

    /**
     * 退款方法
     * @Author yu
     * @date 2021/9/6 15:24
     * @Param [id, refundAmount, productName]
     * @return java.lang.String
     **/

    private String refund(String id,float refundAmount,String productName){
        String InputCharset = "UTF-8";
        String customerNo = "202108240002";
        String key = "n7hPATGKB6aQRfmncrCV";
        String goodNo = "ONEQRCODE";
        String requestGateWayRefundPayXmlurl = "http://pay.chinavbao.com/vbaoPay/cust/payService/QRCodeRefund";
        QRCodeRefundRequest qrCodeRefundRequest = new QRCodeRefundRequest();

        qrCodeRefundRequest.setVersion("6.0");
        qrCodeRefundRequest.setSignType("MD5");
        qrCodeRefundRequest.setInputCharset(InputCharset);
        qrCodeRefundRequest.setCustomerNo(customerNo);
        qrCodeRefundRequest.setGoodNo(goodNo);
        //"YMF" + System.nanoTime()
        qrCodeRefundRequest.setOrderNo(String.valueOf(System.nanoTime())); //退款订单号
        System.out.println("退款订单:"+String.valueOf(System.nanoTime()));

        //通过订单id查询支付时间即表中的start_time
        QueryWrapper<WxProductOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",id);
        WxProductOrder wxProductOrder = wxProductOrderMapper.selectOne(queryWrapper);
        Date date = wxProductOrder.getStartTime();
        System.out.println("date:"+date);
        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMdd");
        String payDate = sdf.format(date);
        System.out.println("payDate:"+payDate);
        qrCodeRefundRequest.setPayDate(payDate); //支付时间，格式YYYYMMDD


        qrCodeRefundRequest.setRefundOrderNo(id); //被退款的订单号，原支付的商户订单号
        qrCodeRefundRequest.setRefundAmount(String.valueOf(refundAmount));  //退款金额，单位元  格式：100.00
        //http://4130y2w273.qicp.vip   http://money.confidant.top
        qrCodeRefundRequest.setNotifyUrl("http://4130y2w273.qicp.vip:9595/getVbao/get");
        qrCodeRefundRequest.setExt1("");
        qrCodeRefundRequest.setExt2(productName);
        VbaoChargeSystemHandler vbaoChargeSystemHandler = new VbaoChargeSystemHandler();
        TradeRequestXml tradeRequestXml = vbaoChargeSystemHandler.creatRequestXml(qrCodeRefundRequest, key, InputCharset, TradeCodeEnum.QRCODE_PAY_REFUND.getCode());
        System.out.println("发送明文报文:" + tradeRequestXml.getOriRequestXml());
        System.out.println("发送密文报文:" + tradeRequestXml.getRequestXml());
        if (tradeRequestXml.getErrMsg() == null) {
            String returnDKPayxml = vbaoChargeSystemHandler.http(requestGateWayRefundPayXmlurl, tradeRequestXml.getRequestXml(), InputCharset);
            System.out.println("返回密文报文" + returnDKPayxml);
            if (null != returnDKPayxml && returnDKPayxml.length() > 0) {
                String returnOriDKPayxml = "";

                try {
                    returnOriDKPayxml = Base64.decode(returnDKPayxml, InputCharset);
                    System.out.println("解密后报文" + returnOriDKPayxml);
                    if (null != returnOriDKPayxml && returnOriDKPayxml.length() > 0) {
                        boolean flag = vbaoChargeSystemHandler.verifySignature(returnOriDKPayxml, key, InputCharset);
                        if (flag) {
                            System.out.println("验签正确");
                            System.out.println(URLDecoder.decode(returnOriDKPayxml, InputCharset));
                            return "OK";
                        }
                    }
                } catch (UnsupportedEncodingException var12) {
                    System.out.println("解析密文报文有误:" + var12.getMessage());
                }
            }
        } else {
            System.out.println(tradeRequestXml.getErrMsg());
        }

        return "NO";
    }

    //更新或者插入余额表
    private void saveOrUpdateBalance(WxProductOrder wxProductOrder) throws Exception {
        //1 根据订单表的人员id，到人员表中找到名字和身份证
        log.info("根据订单表的人员id" + wxProductOrder.getEmployeeId() + "到人员表中找到名字和身份证");
        Map<String, Object> nameAndIdCard = rxEmployeeMapper.getNameAndIdCardById(wxProductOrder.getEmployeeId());
        //2 根据名字和身份证去找余额表中是否有这个人的信息
        String name = (String) nameAndIdCard.get("name");
        String idCard = (String) nameAndIdCard.get("id_card");
        float orderMoney = wxProductOrder.getOrderMoney();
        Map<String, Object> balanceMap = balanceMapper.selectBalance(name, idCard);
        if (MapUtil.isEmpty(balanceMap)) {
            //3 余额表中没有这个人的信息进行insert操作
            log.info("余额表中没有这个人的信息进行insert操作");
            balanceMapper.insertInfo(name, idCard, orderMoney);
        } else {
            //3 余额表中有这个人信息进行update 余额的操作
            log.info("余额表中有这个人信息进行update 余额的操作");
            float personalBalance = (float) balanceMap.get("personal_balance") + orderMoney;
            balanceMapper.updateInfo(name, idCard, personalBalance);
        }
    }

    //插入信息到交易记录表
    private void saveTransactionRecords(WxProductOrder wxProductOrder) throws Exception{
        log.info("正常到期操作插入到交易记录表中");
        WxProduct wxProduct = wxProductMapper.getProductByProductId(wxProductOrder.getProductId());
        TransactionRecords transactionRecords = new TransactionRecords();
        //提前赎回插入
        transactionRecords.setEmployeeId(wxProductOrder.getEmployeeId());
        transactionRecords.setProductName(wxProduct.getProductName());
        transactionRecords.setPayMoney(wxProductOrder.getPayMoney());
        transactionRecords.setStartTime(wxProductOrder.getStartTime());
        transactionRecords.setEndTime(wxProductOrder.getEndTime());
        transactionRecords.setInterest(wxProductOrder.getOrderMoney() - wxProductOrder.getPayMoney());
        transactionRecords.setOrderStatus(Constants.DUE_TO_NORMAL_TRANSACTION);
        transactionRecords.setTransactionAmount(wxProductOrder.getOrderMoney());
        transactionRecordsMapper.insert(transactionRecords);
    }
}
